import os
import tempfile
from .gotypes import Point, Player
from .board import Board, Move
from .encoder import OnePlaneEncoder, SimpleEncoder, SevenPlaneEncoder, AlphaGoEncoder

import numpy as np 
from keras.models import save_model, load_model
from h5py import File

COLS = 'ABCDEFGHJKLMNOPQRST'
PlayerChars = {
    None: ' . ',
    Player.black: ' x ',
    Player.white: ' o ',
}

def PointFromCoords(coords):
    col = COLS.index(coords[0]) + 1
    row = int(coords[1:])
    return Point(row,col)

def CoordsFromPoint(point:Point):
    return f'{COLS[point.col - 1]}{point.row}'

def PrintMove(player:Player, move:Move):
    if move.is_pass:
        s = 'passes'
    elif move.is_resign:
        s = 'resign'
    else:
        s = f'{COLS[move.point.col - 1]}{move.point.row}'
    print(f'{player} {s}: ')

def PrintBoard(board:Board):
    print('    ' + '  '.join(COLS[:board.cols]))
    for r in range(board.rows):
        bump = ' ' if r < 9 else ''
        line = []
        for c in range(board.cols):
            player = board.GetPlayer(Point(r+1,c+1))
            line.append(PlayerChars[player])
        s = ''.join(line)
        print(f'{bump}{r+1} {s}')
    
def SaveModelToH5File(model, f):
    tempfname = 'tmp-kerasmodel.h5'
    try:
        tmpfile = File(tempfname, 'w')
        save_model(model, tmpfile)
        tmpfile.close()
        tmpfile = File(tempfname, 'r')
        root_item = tmpfile.get('/')
        tmpfile.copy(root_item, f, 'kerasmodel')
        tmpfile.close()
    except:
        print('Error in SaveModelToH5File().')

def LoadModelFromH5File(f, custom_objects=None):
    tempfname ='tmp-kerasmodel.h5'
    try:
        tmpfile = File(tempfname, 'w')
        root_item = f.get('kerasmodel')
        for attr_name, attr_value in root_item.attrs.items():
            tmpfile.attrs[attr_name] = attr_value
        for k in root_item.keys():
            f.copy(root_item.get(k), tmpfile, k)
        tmpfile.close()
        return load_model(tempfname, custom_objects=custom_objects)
    except:
        print('Error in LoadModelFromH5File')

class R:

    # 1. For nn.py

    @staticmethod
    def SigmoidDouble(x):
        return 1 / (1 + np.exp(-x))

    @staticmethod
    def Sigmoid(x):
        return np.vectorize(R.SigmoidDouble)(x)

    @staticmethod
    def SigmoidPrimeDouble(x):
        return R.SigmoidDouble(x) * (1 - R.SigmoidDouble(x))

    @staticmethod
    def SigmoidPrime(x):
        return np.vectorize(R.SigmoidPrimeDouble)(x)
    
    @staticmethod
    def GetEncoderByName(name, size):
        if name == 'oneplane':
            return OnePlaneEncoder(size)
        elif name == 'simple':
            return SimpleEncoder(size)
        elif name == 'sevenplane':
            return SevenPlaneEncoder(size)
        elif name == 'alphago':
            return AlphaGoEncoder(size)
    
